home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / shadow-3.1.4 / mkpasswd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-26  |  8.4 KB  |  404 lines

  1. /*
  2.  * Copyright 1990, 1991, John F. Haugh II
  3.  * All rights reserved.
  4.  *
  5.  * Permission is granted to copy and create derivative works for any
  6.  * non-commercial purpose, provided this copyright notice is preserved
  7.  * in all copies of source code, or included in human readable form
  8.  * and conspicuously displayed on all copies of object code or
  9.  * distribution media.
  10.  */
  11.  
  12. #ifndef    lint
  13. static    char    sccsid[] = "@(#)mkpasswd.c    3.9    07:44:14    9/17/91";
  14. static    char    copyright[] = "Copyright 1990, 1991, John F. Haugh II";
  15. #endif
  16.  
  17. #include "config.h"
  18. #include <stdio.h>
  19.  
  20. #if !defined(DBM) && !defined(NDBM) /*{*/
  21.  
  22. main (argc, argv)
  23. int    argc;
  24. char    **argv;
  25. {
  26.     fprintf(stderr, "%s: no DBM database on system - no action performed\n",
  27.         argv[0]);
  28.     exit(0);
  29. }
  30.  
  31. #else /*} defined(DBM) || defined(NDBM) {*/
  32.  
  33. #include <fcntl.h>
  34. #include "pwd.h"
  35. #ifdef    BSD
  36. #include <strings.h>
  37. #define    strchr    index
  38. #define    strrchr    rindex
  39. #else
  40. #include <string.h>
  41. #endif
  42.  
  43. #ifdef    DBM
  44. #include <dbm.h>
  45. #endif
  46. #ifdef    NDBM
  47. #include <ndbm.h>
  48. #include <grp.h>
  49. #include "shadow.h"
  50.  
  51. DBM    *pw_dbm;
  52. DBM    *gr_dbm;
  53. DBM    *sp_dbm;
  54. DBM    *sgr_dbm;
  55. char    *fgetsx();
  56. #endif
  57.  
  58. char    *CANT_OPEN =    "%s: cannot open file %s\n";
  59. char    *CANT_OVERWRITE = "%s: cannot overwrite file %s\n";
  60. #ifdef    DBM
  61. char    *CANT_CREATE =    "%s: cannot create %s\n";
  62. #endif
  63. char    *DBM_OPEN_ERR =    "%s: cannot open DBM files for %s\n";
  64. char    *PARSE_ERR =    "%s: error parsing line\n\"%s\"\n";
  65. char    *LINE_TOO_LONG = "%s: the beginning with \"%.16s ...\" is too long\n";
  66. char    *ADD_REC =    "adding record for name \"%s\"\n";
  67. char    *ADD_REC_ERR =    "%s: error adding record for \"%s\"\n";
  68. char    *INFO =        "added %d entries, longest was %d\n";
  69. #ifdef    NDBM
  70. char    *USAGE =    "Usage: %s [ -vf ] [ -p|g|sp|sg ] file\n";
  71. #else
  72. char    *USAGE =    "Usage: %s [ -vf ] file\n";
  73. #endif
  74.  
  75. char    *Progname;
  76. int    vflg = 0;
  77. int    fflg = 0;
  78. #ifdef    NDBM
  79. int    gflg = 0;
  80. int    sflg = 0;
  81. int    pflg = 0;
  82. #endif
  83.  
  84. void    usage();
  85.  
  86. extern    char    *malloc();
  87. extern    struct    passwd    *sgetpwent();
  88. extern    int    pw_dbm_update();
  89. #ifdef    NDBM
  90. extern    struct    group    *sgetgrent();
  91. extern    struct    spwd    *sgetspent();
  92. extern    struct    sgrp    *sgetsgent();
  93. extern    int    sp_dbm_update();
  94. extern    int    gr_dbm_update();
  95. extern    int    sgr_dbm_update();
  96. #endif
  97.  
  98. /*
  99.  * mkpasswd - create DBM files for /etc/passwd-like input file
  100.  *
  101.  * mkpasswd takes an an argument the name of a file in /etc/passwd format
  102.  * and creates a DBM file keyed by user ID and name.  The output files have
  103.  * the same name as the input file, with .dir and .pag appended.
  104.  *
  105.  * if NDBM is defined this command will also create look-aside files for
  106.  * /etc/group, /etc/shadow, and /etc/gshadow.
  107.  */
  108.  
  109. int
  110. main (argc, argv)
  111. int    argc;
  112. char    **argv;
  113. {
  114.     extern    int    optind;
  115.     extern    char    *optarg;
  116.     FILE    *fp;            /* File pointer for input file        */
  117.     char    *file;            /* Name of input file                 */
  118.     char    *dir;            /* Name of .dir file                  */
  119.     char    *pag;            /* Name of .pag file                  */
  120.     char    *cp;            /* Temporary character pointer        */
  121.     int    flag;            /* Flag for command line option       */
  122. #ifdef    DBM
  123.     int    fd;            /* File descriptor of open DBM file   */
  124. #endif
  125.     int    cnt = 0;        /* Number of entries in database      */
  126.     int    longest = 0;        /* Longest entry in database          */
  127.     int    len;            /* Length of input line               */
  128.     int    errors = 0;        /* Count of errors processing file    */
  129.     char    buf[BUFSIZ*8];        /* Input line from file               */
  130.     struct    passwd    *passwd;    /* Pointer to password file entry     */
  131. #ifdef    NDBM
  132.     struct    group    *group;        /* Pointer to group file entry        */
  133.     struct    spwd    *shadow;    /* Pointer to shadow passwd entry     */
  134.     struct    sgrp    *gshadow;    /* Pointer to shadow group entry      */
  135.     DBM    *dbm;            /* Pointer to new NDBM files          */
  136.     DBM    *dbm_open();        /* Function to open NDBM files        */
  137. #endif
  138.  
  139.     /*
  140.      * Figure out what my name is.  I will use this later ...
  141.      */
  142.  
  143.     if (Progname = strrchr (argv[0], '/'))
  144.         Progname++;
  145.     else
  146.         Progname = argv[0];
  147.  
  148.     /*
  149.      * Figure out what the flags might be ...
  150.      */
  151.  
  152. #ifdef    NDBM
  153.     while ((flag = getopt (argc, argv, "fvpgs")) != EOF)
  154. #else
  155.     while ((flag = getopt (argc, argv, "fv")) != EOF)
  156. #endif
  157.     {
  158.         switch (flag) {
  159.             case 'v':
  160.                 vflg++;
  161.                 break;
  162.             case 'f':
  163.                 fflg++;
  164.                 break;
  165. #ifdef    NDBM
  166.             case 'g':
  167.                 gflg++;
  168.                 if (pflg)
  169.                     usage ();
  170.  
  171.                 break;
  172.             case 's':
  173.                 sflg++;
  174.                 break;
  175.             case 'p':
  176.                 pflg++;
  177.                 if (gflg)
  178.                     usage ();
  179.  
  180.                 break;
  181. #endif
  182.             default:
  183.                 usage ();
  184.         }
  185.     }
  186.  
  187. #ifdef NDBM
  188.     /*
  189.      * Backwards compatibility fix for -p flag ...
  190.      */
  191.  
  192.     if (! sflg && ! gflg)
  193.         pflg++;
  194. #endif
  195.  
  196.     /*
  197.      * The last and only remaining argument must be the file name
  198.      */
  199.  
  200.     if (argc - 1 != optind)
  201.         usage ();
  202.  
  203.     file = argv[optind];
  204.  
  205.     if (! (fp = fopen (file, "r"))) {
  206.         fprintf (stderr, CANT_OPEN, Progname, file);
  207.         exit (1);
  208.     }
  209.  
  210.     /*
  211.      * Make the filenames for the two DBM files.
  212.      */
  213.  
  214.     dir = malloc (strlen (file) + 5);    /* space for .dir file */
  215.     strcat (strcpy (dir, file), ".dir");
  216.  
  217.     pag = malloc (strlen (file) + 5);    /* space for .pag file */
  218.     strcat (strcpy (pag, file), ".pag");
  219.  
  220.     /*
  221.      * Remove existing files if requested.
  222.      */
  223.  
  224.     if (fflg) {
  225.         (void) unlink (dir);
  226.         (void) unlink (pag);
  227.     }
  228.  
  229.     /*
  230.      * Create the two DBM files - it is an error for these files
  231.      * to have existed already.
  232.      */
  233.  
  234.     if (access (dir, 0) == 0) {
  235.         fprintf (stderr, CANT_OVERWRITE, Progname, dir);
  236.         exit (1);
  237.     }
  238.     if (access (pag, 0) == 0) {
  239.         fprintf (stderr, CANT_OVERWRITE, Progname, pag);
  240.         exit (1);
  241.     }
  242.  
  243. #ifdef    NDBM
  244.     if (sflg)
  245.         umask (077);
  246.     else
  247. #endif
  248.     umask (0);
  249. #ifdef    DBM
  250.     if ((fd = open (dir, O_RDWR|O_CREAT|O_EXCL, 0644)) == -1) {
  251.         fprintf (stderr, CANT_CREATE, Progname, dir);
  252.         exit (1);
  253.     } else
  254.         close (fd);
  255.  
  256.     if ((fd = open (pag, O_RDWR|O_CREAT|O_EXCL, 0644)) == -1) {
  257.         fprintf (stderr, CANT_CREATE, Progname, pag);
  258.         unlink (dir);
  259.         exit (1);
  260.     } else
  261.         close (fd);
  262. #endif
  263.  
  264.     /*
  265.      * Now the DBM database gets initialized
  266.      */
  267.  
  268. #ifdef    DBM
  269.     if (dbminit (file) == -1) {
  270.         fprintf (stderr, DBM_OPEN_ERR, Progname, file);
  271.         exit (1);
  272.     }
  273. #endif
  274. #ifdef    NDBM
  275.     if (! (dbm = dbm_open (file, O_RDWR|O_CREAT, 0644))) {
  276.         fprintf (stderr, DBM_OPEN_ERR, Progname, file);
  277.         exit (1);
  278.     }
  279.     if (gflg) {
  280.         if (sflg)
  281.             sgr_dbm = dbm;
  282.         else
  283.             gr_dbm = dbm;
  284.     } else {
  285.         if (sflg)
  286.             sp_dbm = dbm;
  287.         else
  288.             pw_dbm = dbm;
  289.     }
  290. #endif
  291.  
  292.     /*
  293.      * Read every line in the password file and convert it into a
  294.      * data structure to be put in the DBM database files.
  295.      */
  296.  
  297. #ifdef    NDBM
  298.     while (fgetsx (buf, BUFSIZ, fp) != NULL)
  299. #else
  300.     while (fgets (buf, BUFSIZ, fp) != NULL)
  301. #endif
  302.     {
  303.  
  304.         /*
  305.          * Get the next line and strip off the trailing newline
  306.          * character.
  307.          */
  308.  
  309.         buf[sizeof buf - 1] = '\0';
  310.         if (! (cp = strchr (buf, '\n'))) {
  311.             fprintf (stderr, LINE_TOO_LONG, Progname, buf);
  312.             exit (1);
  313.         }
  314.         *cp = '\0';
  315.         len = strlen (buf);
  316.  
  317.         /*
  318.          * Parse the password file line into a (struct passwd).
  319.          * Erroneous lines cause error messages, but that's
  320.          * all.  YP lines are ignored completely.
  321.          */
  322.  
  323.         if (buf[0] == '-' || buf[0] == '+')
  324.             continue;
  325.  
  326. #ifdef    DBM
  327.         if (! (passwd = sgetpwent (buf)))
  328. #endif
  329. #ifdef    NDBM
  330.         if (! (((! sflg && pflg) && (passwd = sgetpwent (buf)))
  331.             || ((sflg && pflg) && (shadow = sgetspent (buf)))
  332.             || ((! sflg && gflg) && (group = sgetgrent (buf)))
  333.             || ((sflg && gflg) && (gshadow = sgetsgent (buf)))))
  334. #endif
  335.         {
  336.             fprintf (stderr, PARSE_ERR, Progname, buf);
  337.             errors++;
  338.             continue;
  339.         }
  340. #ifdef    DBM
  341.         if (vflg)
  342.             printf (ADD_REC, passwd->pw_name);
  343.  
  344.         if (! pw_dbm_update (passwd))
  345.             fprintf (stderr, ADD_REC_ERR,
  346.                 Progname, passwd->pw_name);
  347. #endif
  348. #ifdef    NDBM
  349.         if (vflg) {
  350.             if (!sflg && pflg) printf (ADD_REC, passwd->pw_name);
  351.             if (sflg && pflg) printf (ADD_REC, shadow->sp_namp);
  352.             if (!sflg && gflg) printf (ADD_REC, group->gr_name);
  353.             if (sflg && gflg) printf (ADD_REC, gshadow->sg_name);
  354.         }
  355.         if (! sflg && pflg && ! pw_dbm_update (passwd))
  356.             fprintf (stderr, ADD_REC_ERR,
  357.                 Progname, passwd->pw_name);
  358.  
  359.         if (sflg && pflg && ! sp_dbm_update (shadow))
  360.             fprintf (stderr, ADD_REC_ERR,
  361.                 Progname, shadow->sp_namp);
  362.  
  363.         if (! sflg && gflg && ! gr_dbm_update (group))
  364.             fprintf (stderr, ADD_REC_ERR,
  365.                 Progname, group->gr_name);
  366.  
  367.         if (sflg && gflg && ! sgr_dbm_update (gshadow))
  368.             fprintf (stderr, ADD_REC_ERR,
  369.                 Progname, gshadow->sg_name);
  370. #endif
  371.  
  372.         /*
  373.          * Update the longest record and record count
  374.          */
  375.  
  376.         if (len > longest)
  377.             longest = len;
  378.         cnt++;
  379.     }
  380.  
  381.     /*
  382.      * Tell the user how things went ...
  383.      */
  384.  
  385.     if (vflg)
  386.         printf (INFO, cnt, longest);
  387.  
  388.     exit (errors);
  389.     /*NOTREACHED*/
  390. }
  391.  
  392. /*
  393.  * usage - print error message and exit
  394.  */
  395.  
  396. void
  397. usage ()
  398. {
  399.     fprintf (stderr, USAGE, Progname);
  400.     exit (1);
  401.     /*NOTREACHED*/
  402. }
  403. #endif /*} defined(DBM) || defined(NDBM) */
  404.